<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>说一说从输入URL到页面呈现发生了什么？——网络篇 | yanyan</title>
    <meta name="description" content="Yan&#39;s blog">
    <meta name="generator" content="VuePress 1.4.0">
    <script src="https://cdn.bootcss.com/jquery/3.5.0/jquery.slim.min.js"></script>
  <script src="https://cdn.bootcss.com/fancybox/3.5.7/jquery.fancybox.min.js"></script>
  <link rel="stylesheet" type="text/css" href="https://cdn.bootcss.com/fancybox/3.5.7/jquery.fancybox.min.css">
  <link rel="shortcut icon" type="image/x-icon" href="./favicon.ico">
    
    <link rel="preload" href="/assets/css/0.styles.e1b3f17d.css" as="style"><link rel="preload" href="/assets/js/app.e358a08d.js" as="script"><link rel="preload" href="/assets/js/2.88fa18d1.js" as="script"><link rel="preload" href="/assets/js/24.9ad529fc.js" as="script"><link rel="prefetch" href="/assets/js/10.23baf844.js"><link rel="prefetch" href="/assets/js/11.45c148ba.js"><link rel="prefetch" href="/assets/js/12.e5930132.js"><link rel="prefetch" href="/assets/js/13.0547cd14.js"><link rel="prefetch" href="/assets/js/14.3e67795b.js"><link rel="prefetch" href="/assets/js/15.51129890.js"><link rel="prefetch" href="/assets/js/16.6987f89d.js"><link rel="prefetch" href="/assets/js/17.2807cff5.js"><link rel="prefetch" href="/assets/js/18.855e1707.js"><link rel="prefetch" href="/assets/js/19.6da24791.js"><link rel="prefetch" href="/assets/js/20.e24d4aef.js"><link rel="prefetch" href="/assets/js/21.6efc6fba.js"><link rel="prefetch" href="/assets/js/22.10447f0f.js"><link rel="prefetch" href="/assets/js/23.9154cc24.js"><link rel="prefetch" href="/assets/js/25.4c092e0a.js"><link rel="prefetch" href="/assets/js/26.debdaa01.js"><link rel="prefetch" href="/assets/js/27.8b90b660.js"><link rel="prefetch" href="/assets/js/28.1a323e01.js"><link rel="prefetch" href="/assets/js/29.6f108fc9.js"><link rel="prefetch" href="/assets/js/3.7210d3aa.js"><link rel="prefetch" href="/assets/js/30.e7df1937.js"><link rel="prefetch" href="/assets/js/31.2cb3120f.js"><link rel="prefetch" href="/assets/js/32.eb64932c.js"><link rel="prefetch" href="/assets/js/33.cac3e2f0.js"><link rel="prefetch" href="/assets/js/34.19ea35c4.js"><link rel="prefetch" href="/assets/js/35.fadf5d03.js"><link rel="prefetch" href="/assets/js/36.88b681f1.js"><link rel="prefetch" href="/assets/js/37.2a799db9.js"><link rel="prefetch" href="/assets/js/38.2741a2bf.js"><link rel="prefetch" href="/assets/js/39.359ceb72.js"><link rel="prefetch" href="/assets/js/4.9e938666.js"><link rel="prefetch" href="/assets/js/40.56fd4a10.js"><link rel="prefetch" href="/assets/js/41.e72117ad.js"><link rel="prefetch" href="/assets/js/42.63a6e190.js"><link rel="prefetch" href="/assets/js/43.c8072421.js"><link rel="prefetch" href="/assets/js/44.84cd8367.js"><link rel="prefetch" href="/assets/js/45.0ac810b0.js"><link rel="prefetch" href="/assets/js/46.bb83ff34.js"><link rel="prefetch" href="/assets/js/47.a9333a81.js"><link rel="prefetch" href="/assets/js/48.526b5494.js"><link rel="prefetch" href="/assets/js/49.73b61cc6.js"><link rel="prefetch" href="/assets/js/5.88b252c7.js"><link rel="prefetch" href="/assets/js/50.f34ab799.js"><link rel="prefetch" href="/assets/js/51.d06a49d9.js"><link rel="prefetch" href="/assets/js/52.348d5482.js"><link rel="prefetch" href="/assets/js/6.0face56b.js"><link rel="prefetch" href="/assets/js/7.31eca58d.js"><link rel="prefetch" href="/assets/js/8.69e9ce95.js"><link rel="prefetch" href="/assets/js/9.f25df9e1.js">
    <link rel="stylesheet" href="/assets/css/0.styles.e1b3f17d.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"><!----> <span class="site-name">yanyan</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <!----></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><!---->  <ul class="sidebar-links"><li><section class="sidebar-group collapsable depth-0"><a href="/html/001" class="sidebar-heading clickable"><span>HTML</span> <span class="arrow right"></span></a> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><a href="/css/image" class="sidebar-heading clickable"><span>CSS</span> <span class="arrow right"></span></a> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><a href="/js/001" class="sidebar-heading clickable"><span>JS-基础</span> <span class="arrow right"></span></a> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><a href="/js-v8/001" class="sidebar-heading clickable"><span>JS-V8引擎原理 </span> <span class="arrow right"></span></a> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><a href="/js-async/001" class="sidebar-heading clickable"><span>JS-异步I/O及异步编程</span> <span class="arrow right"></span></a> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><a href="/http/000" class="sidebar-heading clickable open"><span>HTTP</span> <span class="arrow down"></span></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/http/001.html" class="sidebar-link">01 HTTP 的特点？HTTP 的缺点</a></li><li><a href="/http/002.html" class="active sidebar-link">02 说一说从输入URL到页面呈现发生了什么？——网络篇</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/http/002.html#网络请求" class="sidebar-link">网络请求</a></li><li class="sidebar-sub-header"><a href="/http/002.html#网络响应" class="sidebar-link">网络响应</a></li><li class="sidebar-sub-header"><a href="/http/002.html#总结" class="sidebar-link">总结</a></li></ul></li><li><a href="/http/003.html" class="sidebar-link">03 说一说从输入URL到页面呈现发生了什么？——解析算法篇</a></li><li><a href="/http/004.html" class="sidebar-link">04 说一说从输入URL到页面呈现发生了什么？——渲染过程篇</a></li><li><a href="/http/005.html" class="sidebar-link">05 谈谈你对重绘和回流的理解</a></li><li><a href="/http/006.html" class="sidebar-link">06 XSS攻击</a></li><li><a href="/http/007.html" class="sidebar-link">07 CSRF攻击</a></li><li><a href="/http/008.html" class="sidebar-link">08 (传统RSA版本)HTTPS为什么让数据传输更安全</a></li><li><a href="/http/009.html" class="sidebar-link">09 Https TLS 1.2  1.3</a></li><li><a href="/http/010.html" class="sidebar-link">10 Cookie</a></li><li><a href="/http/011.html" class="sidebar-link">11 什么是跨域？浏览器如何拦截响应？如何解决</a></li><li><a href="/http/012.html" class="sidebar-link">12 Http2</a></li><li><a href="/http/013.html" class="sidebar-link">13 Http缓存</a></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><a href="/extend/002" class="sidebar-heading clickable"><span>拓展阅读</span> <span class="arrow right"></span></a> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="说一说从输入url到页面呈现发生了什么？-网络篇"><a href="#说一说从输入url到页面呈现发生了什么？-网络篇" class="header-anchor">#</a> 说一说从输入URL到页面呈现发生了什么？——网络篇</h1> <p>这是一个可以无限难的问题。出这个题目的目的就是为了考察你的 web 基础深入到什么程度。由于水平和篇幅有限，在这里我将把其中一些重要的过程给大家梳理一遍，相信能在绝大部分的情况下给出一个比较惊艳的答案。</p> <p>这里我提前声明，由于是一个综合性非常强的问题，可能会在某一个点上深挖出非常多的细节，我个人觉得学习是一个循序渐进的过程，在明白了整体过程后再去自己研究这些细节，会对整个知识体系有更深的理解。同时，关于延申出来的细节点我都有参考资料，看完这篇之后不妨再去深入学习一下，扩展知识面。</p> <p>好，正题开始。</p> <p>此时此刻，你在浏览器地址栏输入了百度的网址:</p> <div class="language-js extra-class"><pre class="language-js"><code>https<span class="token operator">:</span><span class="token operator">/</span><span class="token regex">/www.baidu.com/</span>
</code></pre></div><h2 id="网络请求"><a href="#网络请求" class="header-anchor">#</a> 网络请求</h2> <h3 id="_1-构建请求"><a href="#_1-构建请求" class="header-anchor">#</a> 1. 构建请求</h3> <p>浏览器会构建请求行:</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 请求方法是GET，路径为根路径，HTTP协议版本为1.1</span>
<span class="token constant">GET</span> <span class="token operator">/</span> <span class="token constant">HTTP</span><span class="token operator">/</span><span class="token number">1.1</span>
</code></pre></div><h3 id="_2-查找强缓存"><a href="#_2-查找强缓存" class="header-anchor">#</a> 2. 查找强缓存</h3> <p>先检查强缓存，如果命中直接使用，否则进入下一步。关于强缓存，如果不清楚可以参考上一篇文章。</p> <h3 id="_3-dns解析"><a href="#_3-dns解析" class="header-anchor">#</a> 3. DNS解析</h3> <p>由于我们输入的是域名，而数据包是通过IP地址传给对方的。因此我们需要得到域名对应的IP地址。这个过程需要依赖一个服务系统，这个系统将域名和 IP 一一映射，我们将这个系统就叫做DNS（域名系统）。得到具体 IP 的过程就是DNS解析。</p> <p>当然，值得注意的是，浏览器提供了DNS数据缓存功能。即如果一个域名已经解析过，那会把解析的结果缓存下来，下次处理直接走缓存，不需要经过 DNS解析。</p> <p>另外，如果不指定端口的话，默认采用对应的 IP 的 80 端口。</p> <h3 id="_4-建立-tcp-连接"><a href="#_4-建立-tcp-连接" class="header-anchor">#</a> 4. 建立 TCP 连接</h3> <p>这里要提醒一点，Chrome 在同一个域名下要求同时最多只能有 6 个 TCP 连接，超过 6 个的话剩下的请求就得等待。
假设现在不需要等待，我们进入了 TCP 连接的建立阶段。首先解释一下什么是 TCP:</p> <blockquote><p>TCP（Transmission Control Protocol，传输控制协议）是一种面向连接的、可靠的、基于字节流的传输层通信协议。
建立 TCP连接经历了下面三个阶段:</p></blockquote> <ol><li>通过三次握手(即总共发送3个数据包确认已经建立连接)建立客户端和服务器之间的连接。</li> <li>进行数据传输。这里有一个重要的机制，就是接收方接收到数据包后必须要向发送方确认, 如果发送方没有接到这个确认的消息，就判定为数据包丢失，并重新发送该数据包。当然，发送的过程中还有一个优化策略，就是把大的数据包拆成一个个小包，依次传输到接收方，接收方按照这个小包的顺序把它们组装成完整数据包。</li> <li>断开连接的阶段。数据传输完成，现在要断开连接了，通过四次挥手来断开连接。
读到这里，你应该明白 TCP 连接通过什么手段来保证数据传输的可靠性，一是三次握手确认连接，二是数据包校验保证数据到达接收方，三是通过四次挥手断开连接。</li></ol> <p>当然，如果再深入地问，比如为什么要三次握手，两次不行吗？第三次握手失败了怎么办？为什么要四次挥手等等这一系列的问题，涉及计算机网络的基础知识，比较底层，但是也是非常重要的细节，希望你能好好研究一下，另外这里有一篇不错的文章，<a href="https://zhuanlan.zhihu.com/p/86426969" target="_blank" rel="noopener noreferrer">点击进入相应的推荐文章<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>，相信这篇文章能给你启发。</p> <h3 id="_5-发送-http-请求"><a href="#_5-发送-http-请求" class="header-anchor">#</a> 5.发送 HTTP 请求</h3> <p>现在TCP连接建立完毕，浏览器可以和服务器开始通信，即开始发送 HTTP 请求。浏览器发 HTTP 请求要携带三样东西:请求行、请求头和请求体。</p> <p>首先，浏览器会向服务器发送请求行,关于请求行， 我们在这一部分的第一步就构建完了，贴一下内容</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 请求方法是GET，路径为根路径，HTTP协议版本为1.1</span>
<span class="token constant">GET</span> <span class="token operator">/</span> <span class="token constant">HTTP</span><span class="token operator">/</span><span class="token number">1.1</span>
</code></pre></div><p>结构很简单，由请求方法、请求URI和HTTP版本协议组成。
同时也要带上请求头，比如我们之前说的Cache-Control、If-Modified-Since、If-None-Match都由可能被放入请求头中作为缓存的标识信息。当然了还有一些其他的属性，列举如下:</p> <div class="language- extra-class"><pre class="language-text"><code>Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cache-Control: no-cache
Connection: keep-alive
Cookie: /* 省略cookie信息 */
Host: www.baidu.com
Pragma: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1
</code></pre></div><p>最后是请求体，请求体只有在POST方法下存在，常见的场景是表单提交</p> <h2 id="网络响应"><a href="#网络响应" class="header-anchor">#</a> 网络响应</h2> <p>HTTP 请求到达服务器，服务器进行对应的处理。最后要把数据传给浏览器，也就是返回网络响应。</p> <p>跟请求部分类似，网络响应具有三个部分:响应行、响应头和响应体。</p> <p>响应行类似下面这样:</p> <div class="language- extra-class"><pre class="language-text"><code>HTTP/1.1 200 OK
</code></pre></div><p>由HTTP协议版本、状态码和状态描述组成。
响应头包含了服务器及其返回数据的一些信息, 服务器生成数据的时间、返回的数据类型以及对即将写入的Cookie信息。</p> <p>举例如下:</p> <div class="language- extra-class"><pre class="language-text"><code>Cache-Control: no-cache
Connection: keep-alive
Content-Encoding: gzip
Content-Type: text/html;charset=utf-8
Date: Wed, 04 Dec 2019 12:29:13 GMT
Server: apache
Set-Cookie: rsv_i=f9a0SIItKqzv7kqgAAgphbGyRts3RwTg%2FLyU3Y5Eh5LwyfOOrAsvdezbay0QqkDqFZ0DfQXby4wXKT8Au8O7ZT9UuMsBq2k; path=/; domain=.baidu.com
</code></pre></div><p>响应完成之后怎么办？TCP 连接就断开了吗？</p> <p>不一定。这时候要判断Connection字段, 如果请求头或响应头中包含Connection: Keep-Alive，表示建立了持久连接，这样TCP连接会一直保持，之后请求统一站点的资源会复用这个连接。</p> <p>否则断开TCP连接, 请求-响应流程结束</p> <h2 id="总结"><a href="#总结" class="header-anchor">#</a> 总结</h2> <p>到此，我们来总结一下主要内容，也就是浏览器端的网络请求过程：</p> <p><a data-fancybox="" title="result" href="/images/html-001.png"><img src="/images/html-001.png" alt="result"></a></p></div> <footer class="page-edit"><!----> <!----></footer> <div class="page-nav"><p class="inner"><span class="prev">
      ←
      <a href="/http/001.html" class="prev">
        01 HTTP 的特点？HTTP 的缺点
      </a></span> <span class="next"><a href="/http/003.html">
        03 说一说从输入URL到页面呈现发生了什么？——解析算法篇
      </a>
      →
    </span></p></div> </main></div><div class="global-ui"></div></div>
    <script src="/assets/js/app.e358a08d.js" defer></script><script src="/assets/js/2.88fa18d1.js" defer></script><script src="/assets/js/24.9ad529fc.js" defer></script>
  </body>
</html>
